home *** CD-ROM | disk | FTP | other *** search
- /*
-
- L'Ecuyer's two-sequence generator with a Bays-Durham shuffle
- on the back-end. Schrage's algorithm is used to perform
- 64-bit modular arithmetic within the 32-bit constraints of
- JavaScript.
-
- Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976)
- 59-64.
-
- L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774.
-
- Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138.
-
- */
-
- function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm
- var t;
-
- t = Math.floor(old / q);
- t = a * (old - (t * q)) - (t * r);
- return Math.round((t < 0) ? (t + m) : t);
- }
-
- function LEnext() { // Return next raw value
- var i;
-
- this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
- this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
-
- /* Extract shuffle table index from most significant part
- of the previous result. */
-
- i = Math.floor(this.state / 67108862);
-
- // New state is sum of generators modulo one of their moduli
-
- this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
-
- // Replace value in shuffle table with generator 1 result
-
- this.shuffle[i] = this.gen1;
-
- return this.state;
- }
-
- // Return next random integer between 0 and n inclusive
-
- function LEnint(n) {
- var p = 1;
-
- // Determine smallest p, 2^p > n
-
- while (n >= p) {
- p <<= 1;
- }
- p--;
-
- /* Generate values from 0 through n by first masking
- values v from 0 to (2^p)-1, then discarding any results v > n.
- For the rationale behind this (and why taking
- values mod (n + 1) is biased toward smaller values, see
- Ferguson and Schneier, "Practical Cryptography",
- ISBN 0-471-22357-3, section 10.8). */
-
- while (true) {
- var v = this.next() & p;
-
- if (v <= n) {
- return v;
- }
- }
- }
-
- // Constructor. Called with seed value
-
- function LEcuyer(s) {
- var i;
-
- this.shuffle = new Array(32);
- this.gen1 = this.gen2 = (s & 0x7FFFFFFF);
- for (i = 0; i < 19; i++) {
- this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
- }
-
- // Fill the shuffle table with values
-
- for (i = 0; i < 32; i++) {
- this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
- this.shuffle[31 - i] = this.gen1;
- }
- this.state = this.shuffle[0];
- this.next = LEnext;
- this.nextInt = LEnint;
- }
-